import random
from tkinter import *

grid = [[0 for _ in range(4)] for _ in range(4)]


def add():
    global grid
    # 使用列表推导式找到所有值为0的元素的下标
    zero_indices = [(i, j) for i, row in enumerate(grid)
                    for j, val in enumerate(row) if val == 0]

    # 确保有0值存在，以避免索引错误
    if zero_indices:
        # 随机选择一个下标
        chosen_index = random.choice(zero_indices)
        grid[chosen_index[0]][chosen_index[1]] = random.choice([2, 4])
    for i in range(4):
        for j in range(4):
            vars[i * 4 + j].set(grid[i][j])


def check():
    global grid
    # 检查是否有空位置
    if any(0 in row for row in grid):
        return False  # 如果有空位置，则游戏未结束

    # 检查四个方向上是否还能滑动并合并
    # 上下左右滑动的逻辑简化为检查每一行/列是否有相邻且相等的元素
    for i in range(4):  # 检查行
        for j in range(3):  # 避免越界
            if grid[i][j] == grid[i][j + 1]:
                return False  # 如果同一行有相邻相等的数，则可以合并，游戏未结束

    for j in range(4):  # 检查列
        for i in range(3):  # 避免越界
            if grid[i][j] == grid[i + 1][j]:
                return False  # 如果同一列有相邻相等的数，则可以合并，游戏未结束

    # 如果以上条件都不满足，则游戏结束
    return True


def color():
    global Buttons
    global vars
    log = [2**i for i in range(13)]
    colors = [
        '#eee4da', '#ede0c8', '#f2b179', '#f59563', '#f67c5f', '#f65e3b',
        '#edcf72', '#edcc61', '#edc850', '#edc53f', '#edc22e', '#edd100',
        '#edbb00'
    ]
    for i in range(16):
        if vars[i].get() != 0:
            Buttons[i].config(bg=colors[log.index(vars[i].get())],
                              activebackground=colors[log.index(
                                  vars[i].get())])
        elif vars[i].get() == 0:
            Buttons[i].config(bg='#ffffff', activebackground='#ffffff')


def move(event):
    global vars
    global Buttons
    side = event.keysym
    if side == 'Down':
        # 先对齐
        for i in range(2, -1, -1):
            for j in range(4):
                a = [False, 0]
                for z in range(3 - i):
                    if grid[i + 1 + z][j] == 0:
                        a[0] = True
                        a[1] = i + 1 + z
                if a[0]:
                    grid[a[1]][j] = grid[i][j]
                    grid[i][j] = 0
        # 再合并
        for i in range(2, -1, -1):
            for j in range(4):
                if grid[i][j] == grid[i + 1][j]:
                    grid[i + 1][j] = grid[i + 1][j] + grid[i][j]
                    grid[i][j] = 0
        # 最后再对齐
        for i in range(2, -1, -1):
            for j in range(4):
                a = [False, 0]
                for z in range(3 - i):
                    if grid[i + 1 + z][j] == 0:
                        a[0] = True
                        a[1] = i + 1 + z
                if a[0]:
                    grid[a[1]][j] = grid[i][j]
                    grid[i][j] = 0
    elif side == 'Up':
        # 先对齐
        for i in range(1, 4, 1):
            for j in range(4):
                a = [False, 0]
                for z in range(i):
                    if grid[i - 1 - z][j] == 0:
                        a[0] = True
                        a[1] = i - 1 - z
                if a[0]:
                    grid[a[1]][j] = grid[i][j]
                    grid[i][j] = 0
        # 再合并
        for i in range(1, 4, 1):
            for j in range(4):
                if grid[i][j] == grid[i - 1][j]:
                    grid[i - 1][j] = grid[i - 1][j] + grid[i][j]
                    grid[i][j] = 0
        # 最后再对齐
        for i in range(1, 4, 1):
            for j in range(4):
                a = [False, 0]
                for z in range(i):
                    if grid[i - 1 - z][j] == 0:
                        a[0] = True
                        a[1] = i - 1 - z
                if a[0]:
                    grid[a[1]][j] = grid[i][j]
                    grid[i][j] = 0
    elif side == 'Left':
        # 先对齐
        for i in range(4):
            for j in range(1, 4, 1):
                a = [False, 0]
                for z in range(j):
                    if grid[i][j - 1 - z] == 0:
                        a[0] = True
                        a[1] = j - 1 - z
                if a[0]:
                    grid[i][a[1]] = grid[i][j]
                    grid[i][j] = 0
        # 再合并
        for i in range(4):
            for j in range(1, 4, 1):
                if grid[i][j] == grid[i][j - 1]:
                    grid[i][j - 1] = grid[i][j - 1] + grid[i][j]
                    grid[i][j] = 0
        # 最后再对齐
        for i in range(4):
            for j in range(1, 4, 1):
                a = [False, 0]
                for z in range(j):
                    if grid[i][j - 1 - z] == 0:
                        a[0] = True
                        a[1] = j - 1 - z
                if a[0]:
                    grid[i][a[1]] = grid[i][j]
                    grid[i][j] = 0
    elif side == 'Right':
        # 先对齐
        for i in range(4):
            for j in range(2, -1, -1):
                a = [False, 0]
                for z in range(3 - j):
                    if grid[i][j + 1 + z] == 0:
                        a[0] = True
                        a[1] = j + 1 + z
                if a[0]:
                    grid[i][a[1]] = grid[i][j]
                    grid[i][j] = 0
        # 再合并
        for i in range(4):
            for j in range(1, 4, 1):
                if grid[i][j] == grid[i][j - 1]:
                    grid[i][j - 1] = grid[i][j - 1] + grid[i][j]
                    grid[i][j] = 0
        # 最后再对齐
        for i in range(4):
            for j in range(2, -1, -1):
                a = [False, 0]
                for z in range(3 - j):
                    if grid[i][j + 1 + z] == 0:
                        a[0] = True
                        a[1] = j + 1 + z
                if a[0]:
                    grid[i][a[1]] = grid[i][j]
                    grid[i][j] = 0
    add()
    color()
    if check():
        for button in Buttons:
            button.config(state='disabled')
            print('Game Over!')
    else:
        score.set(f'得分：{max(var.get() for var in vars)}')


root = Tk()
root.geometry('300x320')
root.title('2048')
root.resizable(0, 0)
root.wm_attributes("-alpha", 0.95)

frame = Frame(root, relief=FLAT)
frame.pack(side='top')

history = [[0 for _ in range(4)] for _ in range(4)]
vars = [IntVar() for _ in range(16)]
for var in vars:
    var.set(0)
Buttons = [
    Button(frame,
           textvariable=i,
           relief=FLAT,
           width=5,
           height=2,
           state='normal') for i in vars
]
for i in range(4):
    for j in range(4):
        Buttons[i * 4 + j].grid(padx=4, pady=2, row=i, column=j)
root.bind("<Up>", move)  # 上键
root.bind("<Down>", move)  # 下键
root.bind("<Left>", move)  # 左键
root.bind("<Right>", move)  # 右键
add()
color()

score = StringVar()
score.set(f'得分：{max(var.get() for var in vars)}')
Label(root, textvariable=score, font=('等线', 20)).pack(side='top')
Button(root, text='退出', command=lambda: exit(),
       font=('等线, 15')).pack(side='top')
root.mainloop()
